---
title: "Interop Cheatsheet"
description: "Cheatsheet for various interop scenarios in ReScript"
canonical: "/docs/manual/interop-cheatsheet"
section: "JavaScript Interop"
order: 1
---

# Interop Cheatsheet

This is a glossary with examples. All the features are described by later pages.

## List of Decorators

> **Note:** In ReScript < 8.3, all our attributes started with the `bs.` prefix. This is no longer needed and our formatter automatically removes them in newer ReScript versions.

{/* Synced from https://github.com/rescript-lang/syntax/blob/123760c5a264da5288eeee5213ddd25eb86d62fe/src/res_printer.ml#L19-L51 */}

### Attributes

- `@as`: [here](./attribute.mdx#usage), [here](./bind-to-js-function.mdx#fixed-arguments), [here](./bind-to-js-function.mdx#constrain-arguments-better) and [here](./generate-converters-accessors.mdx#usage-3)
- [`@deriving`](./generate-converters-accessors.mdx#generate-functions--plain-values-for-variants)
- [`@get`](./bind-to-js-object.mdx#bind-using-special-bs-getters--setters)
- [`@get_index`](./bind-to-js-object.mdx#bind-using-special-bs-getters--setters)
- [`@inline`](./inlining-constants.mdx)
- [`@int`](./bind-to-js-function.mdx#constrain-arguments-better)
- [`@module`](./import-from-export-to-js.mdx#import-a-javascript-modules-content)
- [`@new`](./bind-to-js-object.mdx#bind-to-a-js-object-thats-a-class)
- [`@optional`](./generate-converters-accessors.mdx#optional-labels)
- [`@return`](./bind-to-js-function.mdx#function-nullable-return-value-wrapping)
- `@send`: [here](./bind-to-js-function.mdx#object-method) and [here](./pipe.mdx#js-method-chaining)
- [`@scope`](./bind-to-global-js-values.mdx#global-modules)
- [`@set`](./bind-to-js-object.mdx#bind-using-special-bs-getters--setters)
- [`@set_index`](./bind-to-js-object.mdx#bind-using-special-bs-getters--setters)
- [`@variadic`](./bind-to-js-function.mdx#variadic-function-arguments)
- [`@string`](./bind-to-js-function.mdx#constrain-arguments-better)
- [`@this`](./bind-to-js-function.mdx#modeling-this-based-callbacks)
- [`@uncurry`](./bind-to-js-function.mdx#extra-solution)
- [`@unwrap`](./bind-to-js-function.mdx#trick-2-polymorphic-variant--bsunwrap)
- [`@val`](./bind-to-global-js-values.mdx#global-modules)
- [`@taggedTemplate`](./bind-to-js-function.mdx#tagged_template-functions)
- [`@deprecated`](./attribute.mdx#usage)
- [`genType`](https://github.com/reason-association/genType)
- [`@JSX`](./jsx.mdx)
- `@react.component`: [here](../react/introduction.mdx) and [here](https://github.com/reasonml/reason-react)
- [`@warning`](./attribute.mdx#usage)
- [`@unboxed`](./variant.mdx#untagged-variants)

### Extension Points

- [`%debugger`](./embed-raw-javascript.mdx#debugger)
- [`%external`](./bind-to-global-js-values.mdx#special-global-values)
- [`%raw`](./embed-raw-javascript.mdx#paste-raw-js-code)
- [`%todo`](../../syntax-lookup/extension_todo.mdx)

## Raw JS

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let add = %raw("(a, b) => a + b")
%%raw("const a = 1")
```

```js
var add = (a, b) => a + b;
const a = 1;
```

</CodeTab>

## Global Value

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
@val external setTimeout: (unit => unit, int) => float = "setTimeout"
```

```js
// Empty output
```

</CodeTab>

## Global Module's Value

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
@val @scope("Math")
external random: unit => float = "random"

let someNumber = random()

@val @scope(("window", "location", "ancestorOrigins"))
external length: int = "length"
```

```js
var someNumber = Math.random();
```

</CodeTab>

## Nullable

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let a = Some(5) // compiles to 5
let b = None // compiles to undefined
```

```js
var a = 5;
var b;
```

</CodeTab>

Handling a value that can be `undefined` and `null`, by ditching the `option` type and using `Nullable.t`:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let jsNull = Nullable.null
let jsUndefined = Nullable.undefined
let result1: Nullable.t<string> = Nullable.make("hello")
let result2: Nullable.t<int> = Nullable.fromOption(Some(10))
let result3: option<int> = Nullable.toOption(Nullable.make(10))
```

```js
import * as Caml_option from "./stdlib/caml_option.js";
import * as Core__Nullable from "./stdlib/core__Nullable.js";

var result2 = Core__Nullable.fromOption(10);

var jsNull = null;

var jsUndefined;

var result1 = "hello";

var result3 = Caml_option.nullable_to_opt(10);
```

</CodeTab>

## JS Object

- [Bind to a JS object as a ReScript record](./bind-to-js-object.mdx#bind-to-record-like-js-objects).
- [Bind to a JS object that acts like a hash map](./bind-to-js-object.mdx#bind-to-hash-map-like-js-object).
- [Bind to a JS object that's a class](./bind-to-js-object.mdx#bind-to-a-js-object-thats-a-class).

## Function

### Object Method & Chaining

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
@send external map: (array<'a>, 'a => 'b) => array<'b> = "map"
@send external filter: (array<'a>, 'a => 'b) => array<'b> = "filter"
[1, 2, 3]
  ->map(a => a + 1)
  ->filter(a => mod(a, 2) == 0)
  ->Console.log
```

```js
console.log(
  [1, 2, 3]
    .map(function (a) {
      return (a + 1) | 0;
    })
    .filter(function (a) {
      return a % 2 === 0;
    }),
);
```

</CodeTab>

### Variadic Arguments

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
@module("path") @variadic
external join: array<string> => string = "join"
```

```js
// Empty output
```

</CodeTab>

### Tagged template functions

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// see https://bun.sh/docs/runtime/shell
type result = {exitCode: int}
@module("bun") @taggedTemplate
external sh: (array<string>, array<string>) => promise<result> = "$"

let filename = "index.res"
let result = await sh`ls ${filename}`
```

```js
import * as $$Bun from "bun";
var filename = "index.res";
var result = await $$Bun.$`ls ${filename}`;
```

</CodeTab>

### Polymorphic Function

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
@module("Drawing") external drawCat: unit => unit = "draw"
@module("Drawing") external drawDog: (~giveName: string) => unit = "draw"
```

```js
// Empty output
```

</CodeTab>

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
@val
external padLeft: (
  string,
  @unwrap [
    | #Str(string)
    | #Int(int)
  ])
  => string = "padLeft"

padLeft("Hello World", #Int(4))
padLeft("Hello World", #Str("Message from ReScript: "))
```

```js
padLeft("Hello World", 4);
padLeft("Hello World", "Message from ReScript: ");
```

</CodeTab>

## JS Module Interop

[See here](./import-from-export-to-js.mdx)

## Dangerous Type Cast

Final escape hatch converter. Do not abuse.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
external convertToFloat: int => float = "%identity"
let age = 10
let gpa = 2.1 +. convertToFloat(age)
```

```js
var age = 10;
var gpa = 2.1 + 10;
```

</CodeTab>
